﻿#include "CityDescEx.h"

#include <NFComm/NFCore/NFFileUtility.h>
#include <NFComm/NFCore/NFMD5.h>
#include "MapDataEx.h"

CityDescEx::CityDescEx()
{
	if (EN_OBJ_MODE_INIT == NFShmMgr::Instance()->GetCreateMode()) {
		CreateInit();
	}
	else {
		ResumeInit();
	}
}

CityDescEx::~CityDescEx()
{
}

int CityDescEx::CreateInit()
{
	return 0;
}

int CityDescEx::ResumeInit()
{
	return 0;
}

int CityDescEx::Load()
{
	m_aCityMapData.clear();
	for (int i = 0; i < CityMapDesc::Instance()->GetResNum(); ++i)
	{
		E_CityMap* pDesc = CityMapDesc::Instance()->GetDescByIndex(i);
		CHECK_NULL(0, pDesc);

		CHECK_EXPR(!m_aCityMapData.full(), -1, "m_aCitMMapData space not enough");

		int iRetCode = m_aCityMapData[pDesc->id].LoadMapData(pDesc);
		CHECK_ERR(0, iRetCode, "LoadMapData failed, map id:{}", pDesc->id);
	}
	return 0;
}

int CityDescEx::CheckWhenAllDataLoaded()
{
	return 0;
}

int CCityMapData::CreateInit()
{
	m_iMapID = INVALID_ID;

	m_iXGridNum = 0;
	m_iZGridNum = 0;
	m_iGridSize = DEFAULT_MAP_GRID_SIZE;
	return 0;
}

int CCityMapData::ResumeInit()
{
	return 0;
}

int CCityMapData::LoadMapData(E_CityMap* pstCityMapDesc)
{
    CHECK_NULL(0, pstCityMapDesc);
    std::string strMapPath = NFGlobalSystem::Instance()->GetGlobalPluginManager()->GetConfigPath() + "/" + NFGlobalSystem::Instance()->GetGlobalPluginManager()->GetGame() + "/Mapdata";
    std::string strLevelFile = NFFormatFunc("{}/level/{}.xml", strMapPath, pstCityMapDesc->res_scn.c_str());
    CHECK_EXPR(NFFileUtility::IsFileExist(strLevelFile), -1, "file not exist:{}", strLevelFile);
	std::string md5 = NFMD5::md5file(strLevelFile);

	int iRet = MapDataEx::LoadLevel(m_stMapData, pstCityMapDesc->id, strLevelFile.c_str(), pstCityMapDesc->res_scn.c_str());
	CHECK_ERR(0, iRet, "load level failed:{}", pstCityMapDesc->res_scn.c_str());

	m_stMapData.md5 = md5;

    std::string sceneFileName = NFFormatFunc("{}/scene/{}.xml", strMapPath, m_stMapData.scene_name.c_str());
    md5 = NFMD5::md5file(sceneFileName);

    iRet = MapDataEx::LoadScene(m_stMapData, pstCityMapDesc->id, strMapPath.c_str(), m_stMapData.scene_name.c_str());
	CHECK_ERR(0, iRet, "load scene failed:{}", m_stMapData.scene_name.c_str());

    m_stMapData.scene_md5 = md5;

	m_iMapID = pstCityMapDesc->id;

	iRet = CalcMapGrid();
	CHECK_ERR(0, iRet, "Calc Map Grid Failed [Map:{}]", pstCityMapDesc->id);

	return 0;
}

bool CCityMapData::IsPositionValid(Proto_Vector3& stPos) const
{
	if (stPos.x >= m_stMapData.min.x - DEFAULT_MAP_SIZE_GAP && stPos.x <= m_stMapData.max.x + DEFAULT_MAP_SIZE_GAP)
	{
		if (stPos.z >= m_stMapData.min.z - DEFAULT_MAP_SIZE_GAP && stPos.z <= m_stMapData.max.z + DEFAULT_MAP_SIZE_GAP)
		{
			return true;
		}
	}

	return false;
}

int CCityMapData::CalcMapGrid()
{
	m_iXGridNum = (m_stMapData.max.x - m_stMapData.min.x + 2 * DEFAULT_MAP_SIZE_GAP + m_iGridSize) / m_iGridSize;
	m_iZGridNum = (m_stMapData.max.z - m_stMapData.min.z + 2 * DEFAULT_MAP_SIZE_GAP + m_iGridSize) / m_iGridSize;

	LOGSVR_TRACE("mapid:" << m_iMapID << ", XGridNum:" << m_iXGridNum << ", ZGridNum:" << m_iZGridNum);
	assert(m_iXGridNum * m_iZGridNum < MAX_MAP_GRID_NUM);

	Proto_Vector3 stEnterPos;
	stEnterPos.x = m_stMapData.hero_spawn_list[0].x;
	stEnterPos.y = m_stMapData.hero_spawn_list[0].y;
	stEnterPos.z = m_stMapData.hero_spawn_list[0].z;

	if (!IsPositionValid(stEnterPos))
	{
		LOGSVR_ERROR("map desc id:" << m_iMapID << " enter pos is invalid!");
		return -1;
	}

	return 0;
}

const CCityMapData* CityDescEx::GetCityMapData(int iMapId) const
{
	auto iter = m_aCityMapData.find(iMapId);
	if (iter != m_aCityMapData.end())
	{
		return &iter->second;
	}
	return nullptr;
}
